package cn.edu.sjtu.se.role;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;

import org.apache.commons.net.ftp.FTPReply;

import cn.edu.sjtu.se.Config;
import cn.edu.sjtu.se.metric.Collector;
import cn.edu.sjtu.se.randomfile.RandomFile;

@SuppressWarnings("deprecation")
public class FtpTask extends Thread {

	protected Collector collector;
	protected Config config;

	protected TempClient client;

	protected PrintStream out;
	protected PrintStream err;

	public FtpTask(Collector collector, Config config)
			throws InterruptedException {

		this.collector = collector;
		this.config = config;

		this.out = config.out;
		this.err = config.err;

		client = new TempClient();
	}

	protected void connect() {

		try {

			client.connect(config.getHost(), config.getPort());

			out.println("Connected to " + config.getHost() + " on "
					+ config.getPort());
			out.println(client.getReplyString());

		} catch (IOException e) {

			if (client.isConnected()) {

				try {
					client.disconnect();
				} catch (IOException f) {
				}
			}

			err.println("Could not connect to server.");

			collector.connectFail();
			stop();
		}
	}

	protected void login() {

		try {
			int ret;

			out.println(">USER " + config.getUser());
			ret = client.user(config.getUser());
			out.println(client.getReplyString());

			if (FTPReply.isPositiveCompletion(ret)) {
				return;
			}

			if (!FTPReply.isPositiveIntermediate(ret)) {
				err.println("Log in failed");
				stop();
			}

			out.println(">PASS " + config.getPass());
			ret = client.pass(config.getPass());
			out.println(client.getReplyString());

			if (!FTPReply.isPositiveCompletion(ret)) {
				err.println("Log in failed");
				stop();
			}
		} catch (IOException e) {
			err.println("Log in failed");
			stop();
		}
	}

	protected void list() {

		try {
			out.println(">LIST");

			if (config.getPasv()) {
				client.enterLocalPassiveMode();
			}

			client.do_list(out);
			out.println(client.getReplyString());

		} catch (IOException e) {

			err.println("List failed");
			collector.listFail();
			stop();
		}
	}

	protected void store(RandomFile file) {

		try {
			out.println(">STOR");

			if (config.getPasv()) {
				client.enterLocalPassiveMode();
			}

			client.storeFile(file.getName(), file.getInput());
			out.println(client.getReplyString());

		} catch (IOException e) {
			e.printStackTrace();
			err.println("Store failed");
			collector.storeFail();
			stop();
		}
	}

	protected void retrieve(RandomFile file) {

		try {
			out.println(">RETR");

			if (config.getPasv()) {
				client.enterLocalPassiveMode();
			}

			ByteArrayOutputStream output = new ByteArrayOutputStream();
			client.retrieveFile(file.getName(), output);
			out.println(client.getReplyString());

			if (!file.checkMD5(output.toByteArray())) {
				collector.retrieveFail();
				stop();
			}

		} catch (IOException e) {

			err.println("Retrieve failed");
			collector.retrieveFail();
			stop();
		}
	}

	protected void delete(RandomFile file) {

		try {

			out.println(">DELE");
			client.deleteFile(file.getName());
			out.println(client.getReplyString());
		} catch (IOException e) {

			err.println("Delete failed");
			collector.deleteFail();
			stop();
		}
	}

	protected void quit() {

		if (client.isConnected()) {
			try {
				out.println(">QUIT");
				client.disconnect();
			} catch (IOException f) {
			}
		}
	}

	protected void pwd() {

		try {

			out.println(">PWD");
			out.println(client.printWorkingDirectory());
		} catch (IOException e) {

			err.println("Print Working Directory failed");
			stop();
		}
	}

}
